<?php
declare (strict_types=1);

namespace app\admin\middleware;

use app\common\controller\Config;
use app\common\model\Menu;
use think\facade\Session;
use think\Response;
use think\wenhainan\Auth;
use app\common\model\Admin;
use think\exception\HttpResponseException;

class Verify
{
    /**
     * @var string[] 无需验证方法，* 代表全部，格式：控制器/方法名
     */
    protected $allow = [
        '*/getList',
        'index/*'
    ];

    /**
     * 原点 2021年12月16日16:16:14 admin应用中间件，检测登录，验证权限
     */
    public function handle($request, \Closure $next)
    {
        if (request()->controller() != 'Login' && !Session::get('admin_id')) {

            return redirect(url('login/index')->build());
        }

        //初始化系统参数
        $this->system = cache('system');
        if (!$this->system) {
            $this->system = Config::lists();
            cache('system', $this->system);
        }

        //初始化管理员
        $request->admin = Admin::where('id', Session::get('admin_id'))->find();
        $password_token = Session::get('password_token');
        if (!$password_token) {
            Session::delete('admin_id');
            return redirect(url('login/index')->build());
        }
        if(md5($request->admin->password) != $password_token){
            Session::delete('admin_id');
            Session::delete('password_token');
            return redirect(url('login/index')->build());
        }
        //获取控制器/方法名
        $controller = strtolower($request->controller());
        $action = strtolower($request->action());
        $url = $controller . '/' . $action;

        //初始化菜单名称
        $nav = Menu::getNavigation($url);

        //参数传递
        $request->nav = $nav;
        $request->action = $action;

        //超级管理员无需验证
        if ($request->admin->role_id == 1) {
            return $next($request);
        }
        //检测无需验证控制器和方法名
        if (!$this->allowVerify($controller, $action)) {
            //主验证
            if ($this->masterVerify($nav)) {
                //Auth权限验证
                if (!Auth::instance()->check($url, Session::get('admin_id'))) {
                    $this->error('您没有操作权限');
                }
            }
        }

        return $next($request);

    }

    /**
     * @param $controller
     * @param $action
     * @return bool
     * 原点 2022年3月8日15:41:29 无需验证控制器/方法名检测
     */
    protected function allowVerify($controller, $action): bool
    {
        if (!empty($this->allow)) {
            foreach ($this->allow as $v) {
                $explode = explode('/', $v);
                $compare = $explode[0] != '*' ? $controller : '*';
                $compare_action = $explode[1] != '*' ? $action : '*';
                if ($compare == strtolower($explode[0]) &&
                    $compare_action == strtolower($explode[1])) {
                    return true;
                }
            }
            return false;
        }
        return true;
    }

    /**
     * @param $url
     * @return bool
     * 原点 2022年3月8日15:42:11 主验证 - 仅验证二级菜单，不验证三级及以上
     */
    protected function masterVerify($nav): bool
    {
        return $nav['s_nav'] == '未知' ? false : true;

    }

    /**
     * @param $request
     * @return string
     * 原点 2022年3月8日16:05:39 获取并拼接Param
     */
    protected function getParam($request)
    {
        $param = '';
        $i = 0;
        foreach ($request->get() as $key => $value) {
            $prefix = $i > 0 ? '&' : '?';
            $param .= $prefix . $key . '=' . $value;
            ++$i;
        }
        return $param;
    }

    protected function error($msg = '', string $url = null, $data = '', int $wait = 5, array $header = []): Response
    {
        if (is_null($url)) {
            $url = request()->isAjax() ? '' : 'javascript:history.back(-1);';
        } elseif ($url) {
            $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : app('route')->buildUrl($url);
        }

        $result = [
            'code' => 0,
            'msg'  => $msg,
            'data' => $data,
            'url'  => $url,
            'wait' => $wait,
        ];

        $type = (request()->isJson() || request()->isAjax()) ? 'json' : 'html';

        // 所有form返回的都必须是json，所有A链接返回的都必须是Html
        $type = request()->isGet() ? 'html' : $type;

        if ($type == 'html') {
            $response = view((string)app('config')->get('app.dispatch_error_tmpl'), $result);
        } else if ($type == 'json') {
            $response = json($result);
        }

        throw new HttpResponseException($response);

    }
}
